<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="CommonUtil/CommonUtil.js"></script>
    <script type="text/javascript" charset="utf-8">
        /**
         * 观察者模式：对程序某一对象进行实时观察，当对象状态发生改变时，进行通知
         * 经典案例：订报纸
         */
        //发布者（被观察者）
        var Publish = function (name) {
            this.name = name;
            //接受所有的订阅者，（每个元素是函数类型fn）数组
            this.subscribers = [];
        }
        Publish.prototype.deliver = function (news) {
            var publish = this;
            this.subscribers.forEach(function (fn) {
                //把新消息发给一个订阅者
                fn(news,publish);

            });
            //链式编程
            return this;
        };
        //具体的一个订阅者去订阅报纸的方法
        Function.prototype.subscribe = function (publish) {
            //取得订阅者这个人z3
            var sub = this;
            //some方法，循环遍历数组的每一个元素，执行一个函数
            //如果其中有一个返回true，那么整体返回true
            var alreadyExits=publish.subscribers.some(function (item) {
                return item===sub;
            });
            if (!alreadyExits){
                publish.subscribers.push(this);
            }
            return this;
        };
        //具体的一个订阅者去取消订阅的方法
        Function.prototype.unSubscribe = function (publish) {
            //具体这个人的引用
            var sub = this;
            //filter:过滤函数，循环遍历数组的每一个元素，执行一个函数
            //如果不匹配，则删除该元素
            publish.subscribers = publish.subscribers.filter(function (item) {
                return item!==sub;
            });
            //链式编程
            return this;
        }
        window.onload = function () {
            //实例化发布者对象
            var pub1 = new Publish('第一报社');
            var pub2 = new Publish('第二报社');
            var pub3 = new Publish('第三报社');
            var sub1 = function (news) {
                document.getElementById('sub1').innerHTML += arguments[1].name+':'+news+'\n';
            };
            var sub2 = function (news) {
                document.getElementById('sub2').innerHTML += arguments[1].name+':'+news+'\n';
            };
            //执行订阅方法
            sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3);
            sub2.subscribe(pub1).subscribe(pub2);
            BH.EventUtil.addHandler(document.getElementById('pub1'),'click',function () {
               pub1.deliver(document.getElementById('text1').value)
            });
            BH.EventUtil.addHandler(document.getElementById('pub2'),'click',function () {
                pub2.deliver(document.getElementById('text2').value);
            });
            BH.EventUtil.addHandler(document.getElementById('pub3'),'click',function () {
                pub3.deliver(document.getElementById('text3').value);
            });
            sub1.unSubscribe(pub1);
        }
    </script>
</head>
<body>
    <input id="pub1" type="button" value="第一报社"/>
    <input id="text1" value=""/><br/>
    <input id="pub2" type="button" value="第二报社"/>
    <input id="text2" value=""/><br/>
    <input id="pub3" type="button" value="第三报社"/>
    <input id="text3" value=""/><br/>
    <textarea id="sub1" row="5" cols="30"></textarea>
    <textarea id="sub2" row="5" cols="30"></textarea>
</body>
</html>